<?php
/**
 * Functions for producing common HTML structures.
 *
 * These functions should receive raw data values and are themselves responsible
 * for ensuring they are made safe, where necessary, using htmlentities().
 *
 * These functions should be lightweight and restrict their activity to simple
 * rendering of HTML and supporting formatting operations. Model logic,
 * database access etc. should not be performed by these functions.
 */

require_once('lib.php');

// see print_html_no_investment_shorts()
const NO_INVESTMENT_SHORTS_CANDIDATE = 'No investment suggestions yet &mdash; why not be the first to make one!';
const NO_INVESTMENT_SHORTS_COMPLETE = 'No investments yet &mdash; this is our first month!';
const NO_COMMENTS = 'No comments yet &mdash; why not be the first to make one!';

// see print_html_page_head()
const HEAD_TAB_NONE = 0;
const HEAD_TAB_BLOG = 1;
const HEAD_TAB_UPCOMING = 2;
const HEAD_TAB_ACCOUNT = 3;

/**
 * Print HTML form for creating new investment suggestion.
 *
 * @param array 
 * Raw, ***UNSAFE*** values from a previously unsatisfactory submission of the
 * form. Rendered again for the user so that they can correct the form. This 
 * parameter is always accompanied by a list of constraint errors (the next 
 * parameter). The format is:
 * array(field => value,[...])
 * eg array('name' => '', 'age' => '70')
 *
 * @param array
 * Errors from a previously unsatisfactory submission of the form can be passed
 * to the function which result in error messages being displayed next to their
 * associated fields. The form of this parameter is:
 * array(field => error_message,[...])
 * eg array('name' => 'Required field not completed', 'age' => 'Too old')
 */
function print_html_investment_form($form_values=null, $form_errors=null) {
    global $_CONFIG;
    format_form_fields(
            array('title', 'description', 'charity_name', 'charity_url'),
            $form_errors, $form_values, $formatted_errors, $formatted_values);
    print <<<HTML
<div class="form">
    <form enctype="multipart/form-data" method="POST">
        <h2>Suggest a way to make the world a better place</h2>
        <div class="field">
            <div class="left">Title:</div>
            <div class="right">
                <input class="text-regular" type="text" name="title" maxlength="$_CONFIG->form_max_title_len"
                       value="$formatted_values[title]" />
                $formatted_errors[title]
                <div class="tip">
                    eg Establish new cancer research lab in Oxford
                </div>
            </div>
        </div>
        <div class="field">
            <div class="left">Description:</div>
            <div class="right">
                <textarea name="description" maxlength="$_CONFIG->form_max_desc_len">$formatted_values[description]</textarea>
                $formatted_errors[description]
            </div>
        </div>
        <div class="field">
            <div class="left">Charity name:</div>
            <div class="right">
                <input class="text-regular" type="text" name="charity_name" maxlength="$_CONFIG->form_max_charity_len"
                       value="$formatted_values[charity_name]" />
                $formatted_errors[charity_name]
                <div class="tip">
                    All charities must be recognised by the UK
                    <a target="_blank" href="http://www.charity-commission.gov.uk/">Charity Commission</a>
                </div>
            </div>
        </div>
        <div class="field">
            <div class="left">Charity website:</div>
            <div class="right">
                <input class="text-regular" type="text" name="charity_url" maxlength="$_CONFIG->form_max_url_len"
                       value="$formatted_values[charity_url]" />
                $formatted_errors[charity_url]
                <div class="tip">
                    Where people can look for more information<br />
                    eg http://www.oxfam.org.uk/
                </div>
            </div>
        </div>
        <div class="buttons">
            <input type="submit" value="Save suggestion" class="btn-bold btn" />
            <input type="button" class="btn" value="Cancel" onclick="javascript:window.location.href='/upcoming';" />
        </div>
</form></div>
HTML;
}

/**
 * Print form for submitting comments to investments.
 * @param string $investment_id Record ID of associated investment.
 * @param array see print_html_investment_form()
 * @param array ..
 * @param bool $div_wrap Whether form HTML is wrapped in addressable DIV
 * element used for Ajax updates.
 */
function print_html_comment_form($investment_id, $form_values=null,
                                 $form_errors=null, $div_wrap=true) {
    format_form_fields(
            array('content'),
            $form_errors, $form_values, $formatted_errors, $formatted_values);
    if ($div_wrap) {
        print '<div id="comment_form_container">';
    }
    print '<form id="comment_form"><div class="comment-form">';
    print "<textarea name=\"content\">$formatted_values[content]</textarea>";
    print $formatted_errors['content'];
    $click = "ajax_submit('/investment/$investment_id', '#comment_form');";
    print_html_jsbutton('Share comment', $click);
    print '</div></form>';
    if ($div_wrap) {
        print '</div>';
    }
}

/**
 * Print HTML for investment article.
 * @param array investment data
 */
function print_html_investment_article($investment) {

    // encode all potentially unsafe HTML characters
    $safe_title = htmlentities($investment['title']);
    $safe_charity_name = htmlentities($investment['charity_name']);
    $safe_description = htmlentities($investment['description']);

    print "<div class=\"investment-article\"><h1>$safe_title</h1>";
    print "<img src=\"/investment-image-full/$investment[id]\" /><p>";
    print "<a class=\"charity\" target=\"_blank\" href=\"$investment[charity_url]\">$safe_charity_name</a>";
    print "&nbsp;&mdash;&nbsp;$safe_description</p>";
    print "<div class=\"foot\">";

    // show rating buttons if candidate investment
    if ($investment['type'] == INVESTMENT_TYPE_CANDIDATE) {
        print "<div class=\"action-container\" id=\"likes_box\">";
        print_html_like_buttons($investment);
        print '</div>';
    }

    // show vote button if proposed investment
    if ($investment['type'] == INVESTMENT_TYPE_PROPOSED) {
        print "<div class=\"action-container\" id=\"likes_box\">";
        print_html_vote_button($investment);
        print '</div>';
    }

    // print author and bottom border
    print "<div class=\"author\">";
    print_html_authorbox($investment['author'], $investment['created']);
    print "</div></div><div class=\"border\"></div>";
    print "</div>";
}

function print_html_like_buttons($investment) {
    print_html_likes($investment['id']);
    print_html_jsbutton('I like', "ajax_post('/like/$investment[id]');");
    print '&nbsp;';
    print_html_jsbutton('I don\'t like', "ajax_post('/dislike/$investment[id]');");
}

/**
 * Print HTML for comment in comment list.
 * @param array comment record
 */
function print_html_comment($comment) {
    $safe_content = htmlentities($comment['content']);
    print '<div class="comment-item">';
    print_html_authorbox($comment['author'], $comment['time']);
    print '<div class="content">';
    print "$safe_content</div></div>";
}

/**
 * Print HTML for small box showing author of content and its created time.
 * @param string author's username
 * @param timestamp created
 */
function print_html_authorbox($username, $time) {
    $age = friendly_time($time);
    print "<div class=\"author-box\"><img src=\"/avatar/$username\" />";
    print '<div class="details">';
    print "<b>$username</b>";
    print "<span class=\"subtext\">$age</a></div></div>";
}

/*
 * Print HTML showing like score for investment, eg +3 likes.
 * @param string $investment_id Investment record ID.
 */
function print_html_likes($investment_id) {
    $score = read_like_score($investment_id);
    $class = $score >= 0 ? 'positive' : 'negative';
    $text = sprintf('%+d ', $score) . fnoun(abs($score), 'like', false);
    print "<div class=\"$class\">$text</div>";
}

/**
 * Print HTML button that invokes javascript when clicked.
 * @param string button value
 * @param string javascript statement to invoke
 * @param bool $bold Show button text in bold.
 */
function print_html_jsbutton($text, $onclick, $bold=false) {
    print '<input class="btn';
    if ($bold) {
        print ' btn-bold';
    }
    print "\" type=\"button\" value=\"$text\" ";
    print "onclick=\"javascript:$onclick\" />";
}

/**
 * Head HTML for upcoming investment candidates page.
 */
function print_html_upcoming_head() {
    print '<div class="upcoming-head">';
    print_html_jsbutton('Suggest investment', 'window.location.href=\'/upcoming/new\';');
    print '</div>';
}

/**
 * Print a simple, bold message to the user accompanied by a continue button
 * which navigates to a URL when clicked
 * @param string message
 * @param string URL
 */
function print_html_modal_msg($msg, $continue_href) {
    print "<div class='modal-msg'><h2>$msg</h2>";
    print_html_jsbutton('Continue', "window.location.href='$continue_href';");
    print '</div>';
}

/**
 * Print HTML substitute for an empty investment shorts list.
 * @param string predefined message, see consts NO_INVESTMENT_SHORTS_
 */
function print_html_no_investment_shorts($msg) {
    print "<div class=\"no-investment-shorts\">$msg</div>";
}

/**
 * Print short overview of investment (proposed, candidates or completed).
 * @param array database record associated with investment
 * @param array number of votes received by contending investments. used only
 * for complete investment representing last month's winner.
 */
function print_html_investment_short($investment, $votes=null) {
    global $_CONFIG;

    // crop description
    switch ($investment['type']) {
        case INVESTMENT_TYPE_PROPOSED:
        case INVESTMENT_TYPE_COMPLETE:
            $MAX_LEN = $_CONFIG->investment_short_desc_max_chars_1;
            break;
        case INVESTMENT_TYPE_CANDIDATE:
            $MAX_LEN = $_CONFIG->investment_short_desc_max_chars_2;
            break;
    }
    $cropped_desc = $investment['description'];
    if (strlen($cropped_desc) > $MAX_LEN) {
        $cropped_desc = substr($cropped_desc, 0, $MAX_LEN) . '...';
    }

    // make values HTML safe
    $safe_title = htmlentities($investment['title']);
    $safe_desc = htmlentities($cropped_desc);
    $safe_charity_name = htmlentities($investment['charity_name']);

    $border_class = $investment['type'] == INVESTMENT_TYPE_PROPOSED ? 'soft' : 'hard';
    print "<div class=\"investment-list-item investment-list-item-border-$border_class\">";

    switch ($investment['type']) {
        case INVESTMENT_TYPE_COMPLETE:
            $amount = to_money($investment['amount']);
            $date = date('M Y', intval($investment['proposed']));
            print "<div class=\"time-and-amount\">";
            print "$date<em>$amount</em>";
            print "</div>";
            break;
        case INVESTMENT_TYPE_PROPOSED:
            print "<div class=\"vote\">";
            print_html_vote_button($investment);
            print "</div>";
            break;
    }

    // infer content indent level
    switch ($investment['type']) {
        case INVESTMENT_TYPE_PROPOSED:
        case INVESTMENT_TYPE_COMPLETE:
            $content_indent_class = 'double-indent';
            break;
        case INVESTMENT_TYPE_CANDIDATE:
            $content_indent_class = 'single-indent';
            break;
    }

    // used a lot so makes sense to create variable
    $article_href = '/investment/' . $investment['id'];

    print "<a href=\"$article_href\"><img src=\"/investment-image-thumb/$investment[id]\" /></a>";
    print "<div class=\"details $content_indent_class\">";
    print "<h2><a href=\"$article_href\">$safe_title</a></h2>";
    print "<p><a target=\"_blank\" class=\"charity\" href=\"$investment[charity_url]\">$safe_charity_name</a>";
    print "<a class=\"content\" href=\"$article_href\">&nbsp;&mdash;&nbsp;$safe_desc</a></p>";

    // only show community rating if investment is a candidate type
    if ($investment['type'] == INVESTMENT_TYPE_CANDIDATE) {
        print "<div class=\"rating\">";
        print_html_likes($investment['id']);
        print "</div>";
    }
    
    // footer HTML
    // the whole investment record has been read so counting comment IDs in
    // memory isn't very expensive
    $comments = count_comments($investment['id']);
    $comment_noun = fnoun($comments, 'comment', false);
    print "<a href=\"$article_href\" class=\"sublink\"><b>$comments</b> $comment_noun</a>";

    // only candidate investments show their age
    if ($investment['type'] == INVESTMENT_TYPE_CANDIDATE) {
        $created = friendly_time($investment['created']);
        print "<span class=\"age\">suggested $created</span>";
    }
    
    /* if the investment is of type complete and votes data has been passed
     * to the function then the investment must be the previous month's
     * winner. show the voting results. */
    if ($investment['type'] == INVESTMENT_TYPE_COMPLETE && $votes) {
        print_html_voting_summary($votes);
    }

    print "</div></div>";
}

/**
 * Print HTML button allowing user to vote for proposed investment.
 * @param array investment record 
 */
function print_html_vote_button($investment) {
    $investment_id = $investment['id'];
    print "<div id=\"vote_button_$investment_id\">";
    print_html_jsbutton('Vote', "ajax_post('/vote/$investment_id');", true);
    print '</div>';
}

/**
 * Print HTML summary of investment candidate voting results.
 *
 * @param array (see below)
  * array(
 *      array('title' => 'candidate_a',
 *            'record_id' => '199001a',
 *            'votes' => 345),
 *      [...])
 */
function print_html_voting_summary($data) {
    global $_CONFIG;

    // sum votes
    $votes_sum = 0;
    foreach ($data as $proposed) {
        $votes_sum += $proposed['votes'];
    }

    print "<div class=\"vote-results\"><table>";
    foreach ($data as $data) {
        extract($data);

        // get vote percentage (it's possible that nobody voted)
        $votes_percent = empty($votes) ? 0 : intval(($votes / $votes_sum) * 100);

        // show actual number of votes (and percentage if there were any)
        $votes_text = "<b>$votes</b> " . fnoun($votes, 'vote', false);
        if ($votes > 0) {
            $votes_text .= " <span class=\"percent\">($votes_percent%)</span>";
        }

        // print candidate vote results
        $bar_width_px = $votes_percent * $_CONFIG->pixels_per_vote_percent;
        print "<tr><td class=\"candidate-title\"><a class=\"sublink\" href=\"/investment/$record_id\">$title</a></td>";
        print "<td class=\"vote-count\">$votes_text</span></td>";
        print "<td><div class=\"vote-bar\" style=\"width: {$bar_width_px}px;\"></div></td></tr>";
    }
    print "</table></div>";
}

/**
 * Print basic page HTML foot.
 */
function print_html_foot() {
    print '<div class="footer">';
    print '<a href="javascript:void(0);">About Pepandlove</a>';
    print '<a href="javascript:void(0);">Terms of Service</a>';
    print '<a href="javascript:void(0);">Privacy</a>';
    print '© 2010 Pepandlove Ltd.</div>';
    print '</div></body></html>';
}

/**
 * Print logo and buttons that allow the user to invoke simulation functions,
 * like performing 'end of month' operations and clearing all investement
 * history.
 */
function print_html_head($focus_tab=HEAD_TAB_NONE) {

    // page head HTML
    print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ';
    print '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
    print '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr">';
    print '<head>';
    print '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
    print '<meta http-equiv="Content-Style-Type" content="text/css" />';
    print '<title>Pepandlove</title>';
    print '<link type="text/css" href="/static/default.css" rel="stylesheet" />';
    print '<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>';
    print '<script type="text/javascript" src="/static/default.js"></script>';
    print '</head><body><div class="page">';

    // logo
    print '<div class="head">';
    print '<a href="/"><img src="/static/logo.png" /></a>';

    // tabs
    $tabs = array(
        HEAD_TAB_BLOG => array(
            'text' => 'Blog',
            'href' => '/'),
        HEAD_TAB_UPCOMING => array(
            'text' => 'Upcoming',
            'href' => '/upcoming'),
        HEAD_TAB_ACCOUNT => array(
            'text' => 'Account',
            'href' => 'javascript:void(0);'),
        );
    print '<div class="tabs">';
    foreach ($tabs as $tab_key => $tab_data) {
        print "<a href=\"$tab_data[href]\"";
        if ($tab_key == $focus_tab) {
            print ' class="you-are-here"';
        }
        print ">$tab_data[text]</a>";
    }
    print "</div></div>";
}

/**
 * Print summary of key metric.
 */
function print_html_blog_summary() {
    // random amount and number of people, for now
    $amount = to_money(rand(1, 999999));
    $people = fnoun(rand(1, 999), 'person', true, 'people');
    print "<span class=\"blog-summary\">$people have invested $amount</span>";
}

/**
 * Print simulation control panel.
 */
function print_html_sim() {
    print '<div class="sim"><h2>Play around with the simulation</h2><ul><li>';
    print_html_jsbutton('Generate upcoming', 'http_post(\'/generate-upcoming\', null);');
    print "</li><li>";
    print_html_jsbutton('End of month', 'http_post(\'/end-of-month\', null);');
    print "</li><li>";
    print_html_jsbutton('Reset simulation', 'http_post(\'/reset-simulation\', null);');
    print '</li></ul></div>';
}

?>
